home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 July: Mac OS SDK / Dev.CD Jul 96 SDK / Dev.CD Jul 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc Development Framework / ODFDev / ODF / Found / FWCommon / Sources / FWThrdGd.cpp < prev    next >
Encoding:
Text File  |  1996-04-25  |  9.3 KB  |  311 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                FWThrdGd.cpp
  4. //    Release Version:    $ ODF 1 $
  5. //
  6. //    Copyright:    (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. #include "FWFound.hpp"
  11.  
  12. #ifndef FWTHRDGD_H
  13. #include "FWThrdGd.h"
  14. #endif
  15.  
  16. #ifndef FWPRIMEM_H
  17. #include "FWPriMem.h"
  18. #endif
  19.  
  20. #ifndef FWEXCDEF_H
  21. #include "FWExcDef.h"
  22. #endif
  23.  
  24. #ifdef FW_BUILD_MAC
  25. #pragma segment FWCommon
  26. #endif
  27.  
  28.  
  29. //=====================================================================================
  30. // Class FW_CThreadSafe
  31. //=====================================================================================
  32.  
  33. FW_CThreadGuard *FW_CThreadSafe::fgSwitchGuards = 0;
  34. FW_CThreadGuard *FW_CThreadSafe::fgTerminationGuards = 0;
  35.  
  36.  
  37. //------------------------------------------------------------------------------
  38. // FW_CThreadSafe::NoteCreation
  39. //
  40. // Register the creation of a thread.  This should be called from a critical
  41. // section.  All guards are on the list of termination guards.
  42. //------------------------------------------------------------------------------
  43. void FW_CThreadSafe::NoteCreation(FW_ThreadID newlyCreatedThread)
  44. {
  45. #ifdef    FW_BUILD_MAC
  46.     FW_CThreadGuard *aThreadGuard;
  47.  
  48.     for (aThreadGuard = fgTerminationGuards; aThreadGuard != 0; aThreadGuard = aThreadGuard->fNext)
  49.     {
  50.         // A throw in the middle of this would be bad.  Catch everything and ignore
  51.         // it.  We can't do much else (except assert, and that might also be deadly).
  52.         FW_TRY
  53.         {
  54.             // The "Created" method can call AddThreadInfo to associate a chunk of storage 
  55.             // with this thread.
  56.             aThreadGuard->Created(newlyCreatedThread);
  57.         }
  58.         FW_CATCH_BEGIN
  59.         FW_CATCH_EVERYTHING()
  60.         {
  61.         }
  62.         FW_CATCH_END
  63.     }
  64. #endif
  65. }
  66.  
  67.  
  68. //------------------------------------------------------------------------------
  69. // FW_CThreadSafe::NoteTermination
  70. //
  71. // Register the destruction of a thread.  This should be called from a critical
  72. // section
  73. //------------------------------------------------------------------------------
  74. void FW_CThreadSafe::NoteTermination(FW_ThreadID threadBeingKilled)
  75. {
  76. #ifdef    FW_BUILD_MAC
  77.     FW_CThreadGuard *aThreadGuard;
  78.  
  79.     for (aThreadGuard = fgTerminationGuards; aThreadGuard != 0; aThreadGuard = aThreadGuard->fNext)
  80.     {
  81.         FW_TRY
  82.         {
  83.             // The "Terminating" method can call DeleteThreadInfo to remove the association 
  84.             // of any information with this thread.  
  85.             aThreadGuard->Terminating(threadBeingKilled);
  86.         }
  87.         FW_CATCH_BEGIN
  88.         FW_CATCH_EVERYTHING()
  89.         {
  90.         }
  91.         FW_CATCH_END
  92.     }
  93. #endif
  94. }
  95.  
  96.  
  97. #ifdef    FW_BUILD_MAC
  98. //------------------------------------------------------------------------------
  99. // FW_CThreadSafe::NoteSwitch
  100. //
  101. // Called between threads, indicating which are the old and the new threads.
  102. // This should be called from a critical section.
  103. //------------------------------------------------------------------------------
  104. void FW_CThreadSafe::NoteSwitch(FW_ThreadID aThread, FW_Boolean switchingIn)
  105. {
  106.     FW_CThreadGuard *aThreadGuard;
  107.     unsigned long mask;
  108.     
  109.     if (switchingIn)
  110.         mask = FW_CThreadGuard::kSwitchInThreadEvent;
  111.     else
  112.         mask = FW_CThreadGuard::kSwitchOutThreadEvent;
  113.  
  114.     for (aThreadGuard = fgSwitchGuards; aThreadGuard != 0; aThreadGuard = aThreadGuard->fNext)
  115.     {
  116.         // The "Switch()" method must not throw!  We cannot do an FW_TRY here 
  117.         // because in the case of interest (swapping exception globals), the
  118.         // Switch() would be entered with one set of exception globals and
  119.         // exit with another.  Don't ask how I discovered this...
  120.         if (aThreadGuard->GetMask() & mask)
  121.             aThreadGuard->Switch(aThread, switchingIn);
  122.     }
  123. }
  124. #endif
  125.  
  126.  
  127. //------------------------------------------------------------------------------
  128. // FW_CThreadSafe::RegisterTerminationGuard
  129. //
  130. // Add a ThreadGuard to the list of guardians
  131. //------------------------------------------------------------------------------
  132. void FW_CThreadSafe::RegisterTerminationGuard(FW_CThreadGuard *aThreadGuard)
  133. {
  134.     // Add this guardian to the head of the list
  135.     aThreadGuard->fNext = fgTerminationGuards;
  136.     fgTerminationGuards = aThreadGuard;
  137. }
  138.  
  139.  
  140. //------------------------------------------------------------------------------
  141. // FW_CThreadSafe::DeRegisterTerminationGuard
  142. //
  143. // Remove a ThreadGuard from the list of guardians
  144. //------------------------------------------------------------------------------
  145. void FW_CThreadSafe::DeRegisterTerminationGuard(FW_CThreadGuard *aThreadGuard)
  146. {
  147.     // Remove from the head of the list.  Should be safe as destructors are 
  148.     // executed in reverse order from the constructors
  149.     if (fgTerminationGuards == aThreadGuard)
  150.         fgTerminationGuards = aThreadGuard->fNext;
  151. }
  152.  
  153.  
  154. //------------------------------------------------------------------------------
  155. // FW_CThreadSafe::RegisterSwitchGuard
  156. //
  157. // Add a ThreadGuard to the list of guardians
  158. //------------------------------------------------------------------------------
  159. void FW_CThreadSafe::RegisterSwitchGuard(FW_CThreadGuard *aThreadGuard)
  160. {
  161.     // Add this guardian to the head of the list
  162.     aThreadGuard->fNext = fgSwitchGuards;
  163.     fgSwitchGuards = aThreadGuard;
  164. }
  165.  
  166.  
  167. //------------------------------------------------------------------------------
  168. // FW_CThreadSafe::DeRegisterSwitchGuard
  169. //
  170. // Remove a ThreadGuard from the list of guardians
  171. //------------------------------------------------------------------------------
  172. void FW_CThreadSafe::DeRegisterSwitchGuard(FW_CThreadGuard *aThreadGuard)
  173. {
  174.     // Remove from the head of the list.  Should be safe as destructors are 
  175.     // executed in reverse order from the constructors
  176.     if (fgSwitchGuards == aThreadGuard)
  177.         fgSwitchGuards = aThreadGuard->fNext;
  178. }
  179.  
  180.  
  181. //=====================================================================================
  182. // Class FW_CThreadGuard
  183. //=====================================================================================
  184.  
  185. //------------------------------------------------------------------------------
  186. // FW_CThreadGuard::FW_CThreadGuard
  187. //
  188. // Constructor for FW_CThreadGuard
  189. //------------------------------------------------------------------------------
  190. FW_CThreadGuard::FW_CThreadGuard(unsigned long threadEventMask) :
  191.     fActiveThreads(0),
  192.     fMask(threadEventMask)
  193. {
  194.     // Always check for termination if checking for anything
  195.     if (threadEventMask != 0)
  196.         FW_CThreadSafe::RegisterTerminationGuard(this);
  197.  
  198.     if (threadEventMask & (kSwitchInThreadEvent | kSwitchOutThreadEvent))
  199.         FW_CThreadSafe::RegisterSwitchGuard(this);
  200. }
  201.  
  202.  
  203. //------------------------------------------------------------------------------
  204. // FW_CThreadGuard::~FW_CThreadGuard
  205. //
  206. // Destructor for FW_CThreadGuard
  207. //------------------------------------------------------------------------------
  208. FW_CThreadGuard::~FW_CThreadGuard()
  209. {
  210.     FW_CThreadSafe::DeRegisterTerminationGuard(this);
  211.     FW_CThreadSafe::DeRegisterSwitchGuard(this);
  212.  
  213.     while (fActiveThreads != 0)
  214.     {
  215.         FW_SThreadItem *anItem = fActiveThreads;
  216.  
  217.         fActiveThreads = anItem->fNext;
  218.         FW_PrimitiveFreeBlock(anItem);
  219.     }
  220. }
  221.  
  222.  
  223. #ifdef    FW_BUILD_MAC
  224. //------------------------------------------------------------------------------
  225. // FW_CThreadGuard::Switch
  226. //
  227. // Called between thread switches
  228. //------------------------------------------------------------------------------
  229. void FW_CThreadGuard::Switch(FW_ThreadID, FW_Boolean)
  230. {
  231.     // Default is to do nothing
  232. }
  233. #endif
  234.  
  235.  
  236. //------------------------------------------------------------------------------
  237. // FW_CThreadGuard::AddThreadInfo
  238. //
  239. // Associates a void* with a ThreadID.  
  240. //------------------------------------------------------------------------------
  241. void FW_CThreadGuard::AddThreadInfo(FW_ThreadID aThreadID, void *threadInfo)
  242. {
  243.     FW_SThreadItem *newItem = (FW_SThreadItem *)FW_PrimitiveAllocateBlock(sizeof(FW_SThreadItem));
  244.  
  245.     // [jkp] -- what's the approved method of suicide?
  246.     if (newItem != 0)
  247.     {
  248.         newItem->fThreadID = aThreadID;
  249.         newItem->fThreadInfo = threadInfo;
  250.  
  251.         newItem->fNext = fActiveThreads;
  252.         fActiveThreads = newItem;
  253.     }
  254. }
  255.  
  256.  
  257. //------------------------------------------------------------------------------
  258. // FW_CThreadGuard::GetThreadInfo
  259. //
  260. // Returns the void* with a ThreadID.  
  261. //------------------------------------------------------------------------------
  262.  
  263. void *FW_CThreadGuard::GetThreadInfo(FW_ThreadID aThreadID)
  264. {
  265.     for (FW_SThreadItem *anItem = fActiveThreads; anItem != 0; anItem = anItem->fNext)
  266.     {
  267.         if (anItem->fThreadID == aThreadID)
  268.             return anItem->fThreadInfo;
  269.     }
  270.  
  271.     // [jkp] -- what's the approved method of suicide?
  272.     return 0;
  273. }
  274.  
  275.  
  276. //------------------------------------------------------------------------------
  277. // FW_CThreadGuard::RemoveThreadInfo
  278. //
  279. // Removes the association between a ThreadID and any chunk of data it pointed
  280. // to.  The caller must destroy the chunk of data, we don't know how.
  281. //------------------------------------------------------------------------------
  282. void FW_CThreadGuard::RemoveThreadInfo(FW_ThreadID aThreadID)
  283. {
  284.     FW_SThreadItem **itemPtr = &fActiveThreads;
  285.     FW_SThreadItem *anItem = fActiveThreads;
  286.  
  287.     while (anItem != 0)
  288.     {
  289.         if (anItem->fThreadID == aThreadID)
  290.         {
  291.             *itemPtr = anItem->fNext;
  292.             FW_PrimitiveFreeBlock(anItem);
  293.             return;
  294.         }
  295.         itemPtr = &anItem->fNext;
  296.         anItem = anItem->fNext;
  297.     }
  298.     // [jkp] -- what's the approved method of suicide?
  299. }
  300.  
  301.  
  302. //------------------------------------------------------------------------------
  303. // FW_CThreadGuard::GetMask
  304. //------------------------------------------------------------------------------
  305. unsigned long FW_CThreadGuard::GetMask() const
  306. {
  307.     return fMask;
  308. }
  309.  
  310.  
  311.